//
// Created on 2025/3/11.
//
// Node APIs are not fully supported. To solve the compilation error of the interface cannot be found,
// please include "napi/native_api.h".
// native_renderer.h

// 用户的需求是在鸿蒙Next系统中，结合ArkTS和C++代码，使用OpenGLES来渲染两个不同的纹理。一个是摄像头采集的数据，另一个是ArkUI组件生成的PxlMap数据。他们需要完整的代码案例，但之前的回答只有ArkTS部分，现在需要补充C++的部分。
//
// 首先，我需要确定鸿蒙系统下ArkTS和C++的交互方式。鸿蒙的Native API通常使用Node-API（类似Node.js的N-API）来实现JS/ArkTS与C++的交互。因此，可能需要创建一个Native模块来处理OpenGL渲染，并通过ArkTS调用该模块。
//
// 接下来，用户提到的两个纹理需要分别处理。摄像头数据可能需要通过鸿蒙的相机接口获取，并绑定到OpenGL纹理。而ArkUI的PxlMap数据可能需要从ArkTS传递到C++层，再上传到纹理中。这涉及到跨语言的数据传递，比如将PixelMap的数据指针或字节数组传递给C++。
//
// 然后，OpenGLES的渲染循环应该在C++层实现，包括初始化OpenGL上下文、编译着色器、创建纹理、渲染循环等。ArkTS层需要负责创建XComponent，并将其Surface传递给C++层，以便创建EGL上下文。同时，ArkTS还需要处理UI事件，如更新PxlMap数据时通知C++层更新纹理。
//
// 需要注意的地方包括：
//
// ‌线程管理‌：OpenGL渲染通常在单独的线程中进行，需要确保线程安全和正确的上下文管理。
// ‌资源管理‌：纹理和缓冲区的创建和释放需要正确地在C++层处理，避免内存泄漏。
// ‌跨语言数据传递‌：如何高效地将ArkTS中的图像数据传递到C++层，可能需要使用NativeBuffer或其他鸿蒙提供的机制。
// ‌Surface的传递‌：XComponent的Surface需要传递给C++层，用于创建EGL窗口表面。
// ‌错误处理‌：在C++层需要添加足够的错误检查，比如着色器编译状态、程序链接状态等。
// 可能的实现步骤：
//
// ‌创建Native模块‌：使用Node-API编写C++代码，导出初始化、渲染、更新纹理等方法。
// ‌ArkTS层调用Native模块‌：在XComponent加载时，调用C++的初始化方法，传递Surface和可能的其他参数。
// ‌摄像头数据绑定‌：鸿蒙的相机API可能需要配置输出到Surface或直接绑定到纹理，这部分需要查阅鸿蒙的相机文档。
// ‌PxlMap数据更新‌：当ArkUI的PixelMap数据变化时，通过Native模块的方法将数据传递给C++，更新纹理。
// ‌渲染循环‌：在C++层启动一个渲染线程，持续渲染纹理，或者通过ArkTS层的定时器触发渲染。
// 此外，用户可能需要参考鸿蒙的官方文档，特别是关于Native开发、OpenGLES集成以及Node-API的部分，确保代码符合最新的API规范。同时，示例代码可能需要简化，比如省略错误处理，专注于核心逻辑，但实际开发中必须处理所有可能的错误情况。




#include <napi/native_api.h>
#include <EGL/egl.h>
#include <GLES3/gl3.h>
#include <thread>

class NativeRenderer {
public:
    static napi_value Init(napi_env env, napi_value exports);
    
private:
    static napi_value CreateRenderer(napi_env env, napi_callback_info info);
    static napi_value UpdatePxlMap(napi_env env, napi_callback_info info);
    
    EGLDisplay display_;
    EGLSurface surface_;
    EGLContext context_;
    GLuint program_;
    GLuint cameraTexture_;
    GLuint pxlTexture_;
    std::thread renderThread_;
    bool running_ = false;

    void InitGL();
    void RenderLoop();
    void CreateTexture(GLuint &texture, void *data, int width, int height);
};


// native_renderer.cpp
#include "native_renderer.h"
#include <hilog/log.h>

// 顶点着色器
const char* vertexShaderSource = R"(
#version 300 es
layout(location=0) in vec4 aPosition;
layout(location=1) in vec2 aTexCoord;
out vec2 vTexCoord;
void main() {
    gl_Position = aPosition;
    vTexCoord = aTexCoord;
})";

// 片段着色器
const char* fragmentShaderSource = R"(
#version 300 es
precision mediump float;
in vec2 vTexCoord;
uniform sampler2D uCameraTex;
uniform sampler2D uPxlTex;
out vec4 fragColor;
void main() {
    vec4 cameraColor = texture(uCameraTex, vTexCoord);
    vec4 pxlColor = texture(uPxlTex, vTexCoord);
    fragColor = mix(cameraColor, pxlColor, 0.5);
})";

napi_value NativeRenderer::Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        { "createRenderer", nullptr, CreateRenderer, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "updatePxlMap", nullptr, UpdatePxlMap, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc)/sizeof(desc), desc);
    return exports;
}

napi_value NativeRenderer::CreateRenderer(napi_env env, napi_callback_info info) {
    // 获取Surface对象
    napi_value thisArg;
    void* nativeSurface;
    size_t argc = 1;
    napi_value args;
    napi_get_cb_info(env, info, &argc, args, &thisArg, nullptr);
    
    // 初始化EGL
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, nullptr, nullptr);
    
    // 配置EGL
    const EGLint configAttribs[] = {
        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
        EGL_RED_SIZE, 8,
        EGL_GREEN_SIZE, 8,
        EGL_BLUE_SIZE, 8,
        EGL_ALPHA_SIZE, 8,
        EGL_NONE
    };
    
    EGLConfig config;
    EGLint numConfigs;
    eglChooseConfig(display, configAttribs, &config, 1, &numConfigs);
    
    // 创建Surface
    EGLNativeWindowType window = /* 从napi获取native window */;
    EGLSurface surface = eglCreateWindowSurface(display, config, window, nullptr);
    
    // 创建Context
    const EGLint contextAttribs[] = { 
        EGL_CONTEXT_CLIENT_VERSION, 3,
        EGL_NONE 
    };
    EGLContext context = eglCreateContext(display, config, EGL_NO_CONTEXT, contextAttribs);
    
    // 创建Renderer实例
    NativeRenderer* renderer = new NativeRenderer();
    renderer->display_ = display;
    renderer->surface_ = surface;
    renderer->context_ = context;
    
    // 初始化OpenGL
    eglMakeCurrent(display, surface, surface, context);
    renderer->InitGL();
    
    // 启动渲染线程
    renderer->running_ = true;
    renderer->renderThread_ = std::thread(&NativeRenderer::RenderLoop, renderer);
    
    return nullptr;
}

void NativeRenderer::InitGL() {
    // 编译着色器
    GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
    glCompileShader(vertexShader);
    
    GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
    glCompileShader(fragmentShader);
    
    // 创建程序
    program_ = glCreateProgram();
    glAttachShader(program_, vertexShader);
    glAttachShader(program_, fragmentShader);
    glLinkProgram(program_);
    
    // 初始化纹理
    glGenTextures(1, &cameraTexture_);
    glBindTexture(GL_TEXTURE_2D, cameraTexture_);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    glGenTextures(1, &pxlTexture_);
    glBindTexture(GL_TEXTURE_2D, pxlTexture_);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}

void NativeRenderer::RenderLoop() {
    while (running_) {
        eglMakeCurrent(display_, surface_, surface_, context_);
        
        glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        
        glUseProgram(program_);
        
        // 绑定纹理
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, cameraTexture_);
        glUniform1i(glGetUniformLocation(program_, "uCameraTex"), 0);
        
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, pxlTexture_);
        glUniform1i(glGetUniformLocation(program_, "uPxlTex"), 1);
        
        // 绘制
        GLfloat vertices[] = { /* 顶点数据 */ };
        GLfloat texCoords[] = { /* 纹理坐标 */ };
        
        glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices);
        glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
        
        glEnableVertexAttribArray(0);
        glEnableVertexAttribArray(1);
        
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
        
        eglSwapBuffers(display_, surface_);
    }
}

napi_value NativeRenderer::UpdatePxlMap(napi_env env, napi_callback_info info) {
    // 获取PixelMap数据
    napi_value args;
    size_t argc = 3;
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    void* data;
    size_t length;
    int width, height;
    napi_get_arraybuffer_info(env, args, &data, &length);
    napi_get_value_int32(env, args, &width);
    napi_get_value_int32(env, args, &height);
    
    // 更新纹理
    glBindTexture(GL_TEXTURE_2D, pxlTexture_);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, 
                GL_RGBA, GL_UNSIGNED_BYTE, data);
    
    return nullptr;
}

